package com.example.demo.order.security;

import cn.dev33.satoken.stp.StpUtil;
import com.example.demo.order.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @ClassName AuthenticationUtil
 * @Description 身份认证工具类 - 集成Sa-Token
 * @Author MingChang.Wei
 * @Date 2025/9/26
 **/
@Slf4j
@Component
public class AuthenticationUtil {
    
    // 管理员角色
    private static final String ADMIN_ROLE = "admin";
    
    /**
     * 验证用户身份 - 使用Sa-Token
     */
    public void validateUserAccess(Long requestUserId, Long currentUserId) {
        if (requestUserId == null || currentUserId == null) {
            throw new BusinessException("用户身份验证失败");
        }
        
        // 检查用户是否登录
        if (!StpUtil.isLogin()) {
            throw new BusinessException("用户未登录，请先登录");
        }
        
        // 管理员可以访问所有数据
        if (hasRole(ADMIN_ROLE)) {
            log.debug("管理员访问, adminId={}, targetUserId={}", currentUserId, requestUserId);
            return;
        }
        
        // 普通用户只能访问自己的数据
        if (!requestUserId.equals(currentUserId)) {
            log.warn("用户越权访问: requestUserId={}, currentUserId={}", requestUserId, currentUserId);
            // 记录安全日志
            logSecurityEvent("UNAUTHORIZED_ACCESS", currentUserId, 
                String.format("尝试访问用户%d的数据", requestUserId));
            throw new BusinessException("无权访问他人数据");
        }
    }
    
    /**
     * 获取当前登录用户ID - 从Sa-Token中获取
     */
    public Long getCurrentUserId() {
        try {
            if (!StpUtil.isLogin()) {
                throw new BusinessException("用户未登录");
            }
            return StpUtil.getLoginIdAsLong();
        } catch (Exception e) {
            log.error("获取当前用户ID失败", e);
            throw new BusinessException("获取用户信息失败");
        }
    }
    
    /**
     * 获取当前登录用户名 - 从Sa-Token Session中获取
     */
    public String getCurrentUsername() {
        try {
            if (!StpUtil.isLogin()) {
                throw new BusinessException("用户未登录");
            }
            // 从Session中获取username（需要在登录时存储）
            Object username = StpUtil.getSession().get("username");
            if (username == null) {
                log.error("Session中未找到username，用户ID: {}", getCurrentUserId());
                throw new BusinessException("获取用户信息失败");
            }
            return username.toString();
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("获取当前用户名失败", e);
            throw new BusinessException("获取用户信息失败");
        }
    }
    
    /**
     * 检查用户是否已登录
     */
    public boolean isLogin() {
        return StpUtil.isLogin();
    }
    
    /**
     * 验证管理员权限
     */
    public void validateAdminAccess() {
        if (!StpUtil.isLogin()) {
            throw new BusinessException("用户未登录");
        }
        
        if (!hasRole(ADMIN_ROLE)) {
            Long userId = getCurrentUserId();
            log.warn("非管理员尝试访问管理功能: userId={}", userId);
            logSecurityEvent("ADMIN_ACCESS_DENIED", userId, "尝试访问管理员功能");
            throw new BusinessException("权限不足，需要管理员权限");
        }
    }
    
    /**
     * 检查用户是否具有指定角色
     */
    public boolean hasRole(String role) {
        try {
            if (!StpUtil.isLogin()) {
                return false;
            }
            return StpUtil.hasRole(role);
        } catch (Exception e) {
            log.error("检查用户角色失败: role={}", role, e);
            return false;
        }
    }
    
    /**
     * 检查用户是否具有指定权限
     */
    public boolean hasPermission(String permission) {
        try {
            if (!StpUtil.isLogin()) {
                return false;
            }
            return StpUtil.hasPermission(permission);
        } catch (Exception e) {
            log.error("检查用户权限失败: permission={}", permission, e);
            return false;
        }
    }
    
    /**
     * 验证订单操作权限
     * @param orderUserId 订单所属用户ID
     */
    public void validateOrderAccess(Long orderUserId) {
        Long currentUserId = getCurrentUserId();
        validateUserAccess(orderUserId, currentUserId);
    }
    
    /**
     * 验证购物车操作权限
     * @param cartUserId 购物车所属用户ID
     */
    public void validateCartAccess(Long cartUserId) {
        Long currentUserId = getCurrentUserId();
        validateUserAccess(cartUserId, currentUserId);
    }
    
    /**
     * 验证支付操作权限（更严格的验证）
     * @param orderUserId 订单所属用户ID
     */
    public void validatePaymentAccess(Long orderUserId) {
        if (!StpUtil.isLogin()) {
            throw new BusinessException("用户未登录，无法进行支付");
        }
        
        Long currentUserId = getCurrentUserId();
        
        // 支付操作不允许管理员代替用户操作，必须是用户本人
        if (!orderUserId.equals(currentUserId)) {
            log.warn("支付权限验证失败: orderUserId={}, currentUserId={}", orderUserId, currentUserId);
            logSecurityEvent("PAYMENT_ACCESS_DENIED", currentUserId, 
                String.format("尝试支付用户%d的订单", orderUserId));
            throw new BusinessException("只能支付自己的订单");
        }
        
        // 检查用户状态是否正常
        validateUserStatus(currentUserId);
    }
    
    /**
     * 验证用户状态
     */
    private void validateUserStatus(Long userId) {
        // 检查用户是否被禁用
        if (StpUtil.isDisable(userId)) {
            logSecurityEvent("DISABLED_USER_ACCESS", userId, "被禁用用户尝试操作");
            throw new BusinessException("账户已被禁用，请联系客服");
        }
        
        // 检查会话是否过期
        if (!StpUtil.isLogin()) {
            throw new BusinessException("登录已过期，请重新登录");
        }
    }
    
    /**
     * 获取用户角色列表
     */
    public List<String> getUserRoles() {
        try {
            if (!StpUtil.isLogin()) {
                return List.of();
            }
            return StpUtil.getRoleList();
        } catch (Exception e) {
            log.error("获取用户角色失败", e);
            return List.of();
        }
    }
    
    /**
     * 获取用户权限列表
     */
    public List<String> getUserPermissions() {
        try {
            if (!StpUtil.isLogin()) {
                return List.of();
            }
            return StpUtil.getPermissionList();
        } catch (Exception e) {
            log.error("获取用户权限失败", e);
            return List.of();
        }
    }
    
    /**
     * 记录安全事件日志
     */
    private void logSecurityEvent(String eventType, Long userId, String details) {
        log.warn("安全事件 - 类型: {}, 用户ID: {}, 详情: {}, IP: {}, 时间: {}", 
            eventType, userId, details, getClientIp(), System.currentTimeMillis());
        
        // 实际项目中应该将安全事件记录到专门的安全日志表或安全系统中
        // 可以集成如ELK、Splunk等日志分析系统
        try {
            // 这里可以添加安全事件持久化逻辑
            // 例如：securityLogService.saveSecurityEvent(eventType, userId, details);
            // 或者：kafkaTemplate.send("security-events", securityEvent);
        } catch (Exception e) {
            log.error("记录安全事件失败", e);
        }
    }
    
    /**
     * 获取客户端IP地址
     */
    private String getClientIp() {
        try {
            // Sa-Token可以获取当前请求的IP
            return StpUtil.getTokenInfo().getTag();
        } catch (Exception e) {
            return "unknown";
        }
    }
}
